(define-module (decode))

(use-modules (ice-9 match))
(use-modules (rnrs bytevectors))
(use-modules (srfi srfi-1))
(use-modules (srfi srfi-26))
(use-modules (web uri))

;;;
;;; decode
;;;

(define (acons-list k v alist)
  "Add V to K to alist as list"
  (let ((value (assoc-ref alist k)))
    (if value
        (let ((alist (alist-delete k alist)))
          (acons k (cons v value) alist))
        (acons k (list v) alist))))

(define (list->alist lst)
  "Build a alist of list based on a list of key and values.

   Multiple values can be associated with the same key"
  (let next ((lst lst)
             (out '()))
    (if (null? lst)
        out
        (next (cdr lst) (acons-list (caar lst) (cdar lst) out)))))

(define-public (decode bv)
  "Convert BV querystring or form data to an alist"
  (define string (utf8->string bv))
  (define pairs (map (cut string-split <> #\=)
                     ;; semi-colon and amp can be used as pair separator
                     (append-map (cut string-split <> #\;)
                                 (string-split string #\&))))
  (list->alist (map (match-lambda
                      ((key value)
                       (cons (uri-decode key) (uri-decode value)))) pairs)))
